﻿/* Authors:
 *  Luca Mastrini
 *  Andrea Vandin
 *  Andrea Russino
 */ 

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Net;

using TripLOAMobile.InternalEntities;
using TripLOAMobile.InternalEntities.ExtensionsMethods;
using System.Windows.Forms;
using System.Web.Services.Protocols;

namespace TripLOAMobile
{
    /// <summary>
    /// This class makes all of the communication with the web services.
    /// This class will generate every request for a remote resource.
    /// </summary>
    public class RemoteResourceProvider
    {
        /// <summary>
        /// Status string sent if a transaction succeed.
        /// </summary>
        public const string okStatus = "ok";

        //Entries to localized error strings 
        /// <summary>
        /// Entry to reference for connection error message.
        /// </summary>
        public const string connErr = "ConnErr";
        /// <summary>
        /// Entry to reference for internal server error message.
        /// </summary>
        public const string serverErr = "ServerErr";
        /// <summary>
        /// Entry to reference for geocofing error message.
        /// </summary>
        public const string geocodeErr = "GeoCodeErr";

        /// <summary>
        /// Default password, used for stored profiles.
        /// </summary>
        public const string standardPassword = "******";
        /// <summary>
        /// This is the authentication key to access the web services.
        /// To implement the logout phase just set this to null, and the login form will be displayed
        /// </summary>
        private string authenticationKey;

        private Dictionary<int, bool> booksTracer;
        private Dictionary<int, bool> favoritesTracer;

        private bool cachedAnimation, isListOfVehiclesChanged = false, isBuddyListChanged = false;
        private string cachedLanguage;
        private string pathNewAvatar;
        private string receivedListOfVehiclesMD5, receivedBuddyListMD5;

        /// <summary>
        /// Checks the need to reload the list of vehicles.
        /// </summary>
        /// <returns><c>false</c> if the list is up to date; otherwise <c>true</c>.</returns>
        private bool NeedToLoadTheListOfVehicles()
        {
            if (this.cred.ListVehiclesMD5 == null)
                return true;
            return this.cred.ListVehiclesMD5 != this.receivedListOfVehiclesMD5;
        }

        /// <summary>
        /// Checks the needs to reload the buddy list.
        /// </summary>
        /// <returns><c>false</c> if the list is up to date; otherwise <c>true</c>.</returns>
        private bool NeedToLoadTheBuddyList()
        {
            if (this.cred.BuddyListMD5 == null)
                return true;
            return this.cred.BuddyListMD5 != this.receivedBuddyListMD5;
        }

        /// <summary>
        /// Reloads the list of vehicles.
        /// </summary>
        /// <returns>The updated list of vehicles</returns>
        public List<WS_SoapLogin.VehicleInfo> GetListOfVehicles()
        {
            if (this.NeedToLoadTheListOfVehicles())
            {
                WS_SoapLogin.SoapUser soapUser = new TripLOAMobile.WS_SoapLogin.SoapUser();
                WS_SoapLogin.WSUserVehicle wsuv = soapUser.GetUserVehicleList(this.authenticationKey);
                if (wsuv.Status == okStatus)
                {
                    this.cred.setListOfVehicles(wsuv);
                    this.isListOfVehiclesChanged = true;
                }
            }
            return this.cred.ListOfVeichles;
        }

        /// <summary>
        /// Reloads the buddy list.
        /// </summary>
        /// <returns>The updated buddy list</returns>
        public List<WS_SoapLogin.UserInfo> GetBuddyList()
        {
            if (this.NeedToLoadTheBuddyList())
            {
                WS_SoapLogin.SoapUser soapUser = new TripLOAMobile.WS_SoapLogin.SoapUser();
                WS_SoapLogin.WSUser res = soapUser.GetBuddyList(this.authenticationKey);
                if (res.Status == "ok")
                {
                    this.cred.setBuddyList(res);
                    this.isBuddyListChanged = true;
                }
            }
            return this.cred.BuddyList;
        }

        /// <summary>
        /// Restores the settings to that at login time.
        /// </summary>
        public void RememberSettingsAtLoginTime()
        {
            pathNewAvatar = null;
            this.cachedAnimation = this.GetUserAnimationTheme();
            this.cachedLanguage = this.cred.Language;
        }

        /// <summary>
        /// Determines whether the animation is changed since the login.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the animation is changed; otherwise, <c>false</c>.
        /// </returns>
        public bool IsAnimationChanged()
        {
            return this.cachedAnimation != this.cred.UseTriploaAnimationTheme;
        }

        /// <summary>
        /// Determines whether the language is changed since the login.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the language is changed; otherwise, <c>false</c>.
        /// </returns>
        public bool IsLanguageChanged()
        {
            return this.cachedLanguage != this.cred.Language;
        }

        /// <summary>
        /// Checks if any information is changed lince login and, if so, updates the profile in cache.
        /// </summary>
        private void UpdateProfileInCacheIfNeeded()
        {
            if ((this.pathNewAvatar != null) || this.IsAnimationChanged() || this.IsLanguageChanged() || this.isListOfVehiclesChanged || this.isBuddyListChanged)
                m_CacheMan.MT_SaveCriticalData(cred, cred.Username);
        }

        /// <summary>
        /// Sets the user animation theme.
        /// </summary>
        /// <param name="useTriploaMobileAnimationTheme">
        /// If set to <c>true</c> use the triploa mobile animation theme; 
        /// otherwise use the windows mobile one.
        /// </param>
        public void SetUserAnimationTheme(bool useTriploaMobileAnimationTheme)
        {
            this.cred.setAnimationTheme(useTriploaMobileAnimationTheme);
        }

        /// <summary>
        /// Sets the user language.
        /// </summary>
        /// <param name="newLanguage">The new language.</param>
        public void SetUserLanguage(string newLanguage)
        {
            this.cred.Language = newLanguage;
        }

        /// <summary>
        /// Gets the user language.
        /// </summary>
        /// <returns>The user language</returns>
        public string GetUserLanguage()
        {
            return cred.Language;
        }

        /// <summary>
        /// Gets the user animation theme.
        /// </summary>
        /// <returns><c>true</c> if triploa mobile animation theme has to be used; otherwise <c>false</c>.</returns>
        public bool GetUserAnimationTheme()
        {
            return cred.UseTriploaAnimationTheme;
        }

        /// <summary>
        /// Changes the Avatar associated to the user, and updates the visualized one. 
        /// The association isn't definitively associated to the user until logout.
        /// </summary>
        /// <param name="path">Local path for the image</param>
        internal void SetAndLoadCurrentAvatar(string path)
        {
            cred.PathAvatar = path;
        }

        #region members about search
        private int latestIndexReturned;
        private SearchCriteria lastSearchedCriteria;
        private int maxNumberOfResult;
        #endregion

        /// <summary>
        /// This is the representation of the cache.
        /// Just this class should access to the cache, making it invisible to the rest
        /// of the application
        /// </summary>
        private CacheManager m_CacheMan;

        /// <summary>
        /// Initializes a new instance of the <see cref="RemoteResourceProvider"/> class.
        /// </summary>
        public RemoteResourceProvider()
        {
            authenticationKey = null;
            this.booksTracer = new Dictionary<int, bool>();
            this.favoritesTracer = new Dictionary<int, bool>();
            m_CacheMan = new CacheManager("cacheFolder");
            this.maxNumberOfResult = 5;
        }

        /// <summary>
        /// This class contains the informations for callback:
        /// <list type="bullet">
        /// <item><description>the returning control;</description></item>
        /// <item><description>the callback delegate;</description></item>
        /// <item><description>the state to use for request;</description></item>
        /// </list>
        /// The class is parameterized on the callback type and on the state type.
        /// </summary>
        /// <typeparam name="DlgType">Callback delegate type</typeparam>
        /// <typeparam name="ArgType">Type of the state for request</typeparam>
        private class RemoteRequest<DlgType, ArgType>
        {
            Control control;
            DlgType dlg;
            ArgType state;

            /// <summary>
            /// Initializes a new instance of the <see cref="RemoteRequest&lt;DlgType, ArgType&gt;"/> class.
            /// </summary>
            /// <param name="control">The returning control.</param>
            /// <param name="dlg">The response handler delegate.</param>
            /// <param name="state">The state.</param>
            public RemoteRequest(Control control, DlgType dlg, ArgType state)
            {
                this.control = control;
                this.dlg = dlg;
                this.state = state;
            }

            /// <summary>
            /// Gets the response handler.
            /// </summary>
            /// <value>The response handler.</value>
            public DlgType ResponseHandler { get { return dlg; } }
            /// <summary>
            /// Gets the state.
            /// </summary>
            /// <value>The state.</value>
            public ArgType State { get { return state; } }
            /// <summary>
            /// Gets the returning control.
            /// </summary>
            /// <value>The returning control.</value>
            public Control Control { get { return control; } }
        }

        /// <summary>
        /// Base-class for all the ResponseEvent raised on a response receiving from the system.
        /// It provides a status string for each communication.
        /// </summary>
        public class ResponseEventArgs : EventArgs
        {
            string status;

            /// <summary>
            /// Initializes a new instance of the <see cref="ResponseEventArgs"/> class.
            /// </summary>
            /// <param name="status">The status.</param>
            public ResponseEventArgs(string status)
                : base()
            {
                this.status = status;
            }

            /// <summary>
            /// Gets the response status.
            /// </summary>
            /// <value>The status.</value>
            public string Status { get { return status; } }
        }

        #region Methods and members about the current user

        /// <summary>
        /// Set of informations related to the actual logged user
        /// </summary>
        private Credentials cred;
        private WS_SoapLogin.UserInfo actualUser;

        /// <summary>
        /// Gets the average feedbacks value for the actual logged user.
        /// </summary>
        /// <returns>Average of feedbacks</returns>
        public decimal GetCurrentFeedbacks()
        {
            return actualUser.NumericFeedbacks;
        }

        /// <summary>
        /// Gets the username of the actual logged user
        /// </summary>
        /// <returns>Username</returns>
        internal string GetCurrentUserName()
        {
            return (actualUser != null) ?
                string.Format("{0}", actualUser.Username) :
                "";
        }

        /// <summary>
        /// Gets the avatar of the actual logged user
        /// </summary>
        /// <returns>Avatar</returns>
        internal Image GetCurrentAvatar()
        {
            if (cred.Avatar == null) return Properties.Resources.unknownUser;
            return cred.Avatar;
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="GetCurrentProfile"/> and <see cref="GetProfile"/>.
        /// Provides the received profile and a status string for each communication.
        /// </summary>
        public class ProfileResponseEventArgs : ResponseEventArgs
        {
            WS_SoapLogin.ProfileInfo profile;

            /// <summary>
            /// Initializes a new instance of the <see cref="ProfileResponseEventArgs"/> class.
            /// </summary>
            /// <param name="profile">The profile.</param>
            /// <param name="status">The status.</param>
            public ProfileResponseEventArgs(WS_SoapLogin.ProfileInfo profile, string status)
                : base(status)
            {
                this.profile = profile;
            }

            /// <summary>
            /// Gets the profile.
            /// </summary>
            /// <value>The profile.</value>
            public WS_SoapLogin.ProfileInfo Profile { get { return profile; } }
        }
        /// <summary>
        /// Response hander for <see cref="GetCurrentProfile"/> and <see cref="GetProfile"/> requests.
        /// </summary>
        public delegate void ProfileResponseHandler(ProfileResponseEventArgs e);

        #region User Profile
        /// <summary>
        /// Makes an asynchronous request to the system for the current profile.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        public void GetCurrentProfile(Control requirer, ProfileResponseHandler callback)
        {
            RemoteRequest<ProfileResponseHandler, int> data = new RemoteRequest<ProfileResponseHandler, int>(requirer, callback, actualUser.UserID);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetProfile((RemoteRequest<ProfileResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a user profile.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="userID">The requested user ID.</param>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        public void GetProfile(int userID, Control requirer, ProfileResponseHandler callback)
        {
            RemoteRequest<ProfileResponseHandler, int> data = new RemoteRequest<ProfileResponseHandler, int>(requirer, callback, userID);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetProfile((RemoteRequest<ProfileResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system for a user profile.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetProfile(RemoteRequest<ProfileResponseHandler, int> data)
        {
            int userId = data.State;

            WS_SoapLogin.WSUserProfile profile;
            try
            {
                WS_SoapLogin.SoapUser temp = new WS_SoapLogin.SoapUser();
                profile = temp.getProfile(authenticationKey, userId);

                string status = profile.Status == okStatus ? profile.Status : profile.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.BeginInvoke(data.ResponseHandler, new ProfileResponseEventArgs(profile.Payload[0], status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new ProfileResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new ProfileResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new ProfileResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion

        #region Messaging
        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="GetUnreadMessages"/> and <see cref="GetReceivedMessages"/>.
        /// Provides the received messages and a status string for each communication.
        /// </summary>
        public class MessageResponseEventArgs : ResponseEventArgs
        {
            WS_SoapMessage.Message[] messages;

            /// <summary>
            /// Initializes a new instance of the <see cref="MessageResponseEventArgs"/> class.
            /// </summary>
            /// <param name="m">The m.</param>
            /// <param name="status">The status.</param>
            public MessageResponseEventArgs(WS_SoapMessage.Message[] m, string status)
                : base(status)
            {
                this.messages = m;
            }

            /// <summary>
            /// Gets the messages.
            /// </summary>
            /// <value>The messages.</value>
            public WS_SoapMessage.Message[] Messages { get { return messages; } }
        }

        /// <summary>
        /// Rapresent the state to working with, used by the requiring thread for <see cref="GetUnreadMessages"/> request.
        /// </summary>
        private class ReceivedMessageReq
        {
            public WS_SoapMessage.Message message;
            public string[] receivers;

            /// <summary>
            /// Initializes a new instance of the <see cref="MessageState"/> class.
            /// </summary>
            /// <param name="m">The m.</param>
            /// <param name="r">The r.</param>
            public ReceivedMessageReq(WS_SoapMessage.Message m, string[] r)
            {
                message = m;
                receivers = r;
            }
        }

        /// <summary>
        /// Rapresent the state to working with, used by the requiring thread for <see cref="GetReceivedMessages"/> request.
        /// </summary>
        private class UnreadMessageReq
        {
            public int start;
            public int max;

            /// <summary>
            /// Initializes a new instance of the <see cref="MessageState_2"/> class.
            /// </summary>
            /// <param name="s">The s.</param>
            /// <param name="m">The m.</param>
            public UnreadMessageReq(int s, int m)
            {
                start = s;
                max = m;
            }
        }

        /// <summary>
        /// Response hander for <see cref="GetUnreadMessages"/> and <see cref="GetReceivedMessages"/> requests.
        /// </summary>
        public delegate void MessageResponseHandler(MessageResponseEventArgs e);

        /// <summary>
        /// Makes an asynchronous request to the system for unread messages.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        public void GetUnreadMessages(Control requirer, MessageResponseHandler callback)
        {
            RemoteRequest<MessageResponseHandler, object> data = new RemoteRequest<MessageResponseHandler, object>(requirer, callback, null);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetUnreadMessages((RemoteRequest<MessageResponseHandler, object>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system for unread messages.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetUnreadMessages(RemoteRequest<MessageResponseHandler, object> data)
        {
            WS_SoapMessage.WSMessage messages;
            try
            {
                WS_SoapMessage.SoapMessage temp = new WS_SoapMessage.SoapMessage();
                messages = temp.GetUnreadMessages(this.authenticationKey);

                string status = messages.Status == okStatus ? messages.Status : messages.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(messages.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a subset of received messages.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="start">The index of the first message, in descending temporal order.</param>
        /// <param name="max">Max number of messages.</param>
        public void GetReceivedMessages(Control requirer, MessageResponseHandler callback, int start, int max)
        {
            UnreadMessageReq msgState = new UnreadMessageReq(start, max);
            RemoteRequest<MessageResponseHandler, UnreadMessageReq> data = new RemoteRequest<MessageResponseHandler, UnreadMessageReq>(requirer, callback, msgState);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetReceivedMessages((RemoteRequest<MessageResponseHandler, UnreadMessageReq>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system for received messages.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetReceivedMessages(RemoteRequest<MessageResponseHandler, UnreadMessageReq> data)
        {
            WS_SoapMessage.WSMessage messages;
            try
            {
                WS_SoapMessage.SoapMessage temp = new WS_SoapMessage.SoapMessage();
                messages = temp.GetReceivedMessages(this.authenticationKey, data.State.start, data.State.max);

                string status = messages.Status == okStatus ? messages.Status : messages.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(messages.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new MessageResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system to mark a message as read.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="messageID">The message ID to process.</param>
        public void MarkMessageAsRead(Control requirer, BooleanResponseHandler callback, int messageID)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, messageID);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_MarkMessageAsRead((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system to mark a message as read.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_MarkMessageAsRead(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int messageID = data.State;

            try
            {
                WS_SoapMessage.SoapMessage temp = new WS_SoapMessage.SoapMessage();
                WS_SoapMessage.WSBool res = temp.MarkMessageAsRead(authenticationKey, messageID);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system to send a message.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="message">The message.</param>
        /// <param name="receivers">The list of receivers.</param>
        public void SendMessage(Control requirer, BooleanResponseHandler callback, WS_SoapMessage.Message message, string[] receivers)
        {
            ReceivedMessageReq msgState = new ReceivedMessageReq(message, receivers);
            RemoteRequest<BooleanResponseHandler, ReceivedMessageReq> data = new RemoteRequest<BooleanResponseHandler, ReceivedMessageReq>(requirer, callback, msgState);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendMessage((RemoteRequest<BooleanResponseHandler, ReceivedMessageReq>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system to send a message.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendMessage(RemoteRequest<BooleanResponseHandler, ReceivedMessageReq> data)
        {
            ReceivedMessageReq msgState = data.State;

            try
            {
                WS_SoapMessage.SoapMessage temp = new WS_SoapMessage.SoapMessage();
                WS_SoapMessage.WSBool res = temp.SendMessage(authenticationKey, msgState.message, msgState.receivers);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system to delete a message.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="messageID">The message ID to process.</param>
        public void DeleteMessage(Control requirer, BooleanResponseHandler callback, int messageID)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, messageID);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_DeleteMessage((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system to delete a message.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_DeleteMessage(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int messageID = data.State;

            try
            {
                WS_SoapMessage.SoapMessage temp = new WS_SoapMessage.SoapMessage();
                WS_SoapMessage.WSBool res = temp.DeleteMessage(authenticationKey, messageID);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion;

        #endregion

        #region Methods about login
        /// <summary>
        /// Gets a list of all the cached profiles.
        /// During this process no a file is really decrypted and read.
        /// </summary>
        /// <param name="userNames">The list of cached usernames.</param>
        /// <param name="arePwdSaved">The list password saved flags.</param>
        public void GetProfiles(out string[] userNames, out bool[] arePwdSaved)
        {
            m_CacheMan.GetProfiles(out userNames, out arePwdSaved);
        }

        /// <summary>
        /// Indicates if the application is logged.
        /// </summary>
        /// <returns><c>true</c> if logged; otherwise <c>false</c>.</returns>
        public bool IsLogged()
        {
            return authenticationKey != null;
        }

        /// <summary>
        /// Makes an asynchronous request for login to the system.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="userName">The username.</param>
        /// <param name="pwd">The password.</param>
        /// <param name="savePassword">Set to <c>true</c> to cache the password.</param>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        public void SendLoginRequest(string userName, string pwd, bool savePassword, Control control, LoginResponseHandler callback)
        {
            LoginReq data = new LoginReq(userName, pwd, savePassword);
            RemoteRequest<LoginResponseHandler, LoginReq> req = new RemoteRequest<LoginResponseHandler, LoginReq>(control, callback, data);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendLoginRequest((RemoteRequest<LoginResponseHandler, LoginReq>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, req);
        }

        /// <summary>
        /// Makes an asynchronous request for login to the system, using cached data associated to the username.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="userName">The username.</param>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        public void SendLoginRequest(string userName, Control control, LoginResponseHandler callback)
        {
            RemoteRequest<LoginResponseHandler, string> data = new RemoteRequest<LoginResponseHandler, string>(control, callback, userName);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendLoginRequest((RemoteRequest<LoginResponseHandler, string>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Rapresent the state to working with, used by the requiring thread for <see cref="SendLoginRequest"/> request.
        /// </summary>
        private class LoginReq
        {
            public string username, password;
            public bool savePassword;

            /// <summary>
            /// Initializes a new instance of the <see cref="LoginReq"/> class.
            /// </summary>
            /// <param name="userName">The username.</param>
            /// <param name="pwd">The password.</param>
            /// <param name="savePassword">Set to <c>true</c> to cache the password.</param>
            public LoginReq(string userName, string pwd, bool savePassword)
            {
                this.username = userName;
                this.password = pwd;
                this.savePassword = savePassword;
            }
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="GetLoginRequest"/>.
        /// Provides the a small set of information for the user, the login status and a status string for each communication.
        /// </summary>
        public class LoginEventArgs : ResponseEventArgs
        {
            WS_SoapLogin.UserInfo user;
            bool succeed;

            /// <summary>
            /// Initializes a new instance of the <see cref="LoginEventArgs"/> class.
            /// </summary>
            /// <param name="user">The user.</param>
            /// <param name="status">The status.</param>
            /// <param name="succeed">Set to <c>true</c> if succeed.</param>
            public LoginEventArgs(WS_SoapLogin.UserInfo user, string status, bool succeed)
                : base(status)
            {
                this.user = user;
                this.succeed = succeed;
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="LoginEventArgs"/> class.
            /// </summary>
            /// <param name="status">The status.</param>
            /// <param name="succeed">Set to <c>true</c> if succeed.</param>
            public LoginEventArgs(string status, bool succeed)
                : this(null, status, succeed) { }

            /// <summary>
            /// Gets the user informations.
            /// </summary>
            /// <value>The user informations.</value>
            public string User
            {
                get
                {
                    return (user != null) ?
                        string.Format("{0} ({1})", user.Username, user.NumericFeedbacks) :
                        "";
                }
            }
            /// <summary>
            /// Gets the user ID.
            /// </summary>
            /// <value>The user ID.</value>
            public int UserID { get { return (user != null) ? user.UserID : 0; } }
            /// <summary>
            /// Gets a value indicating whether the login is succeed.
            /// </summary>
            /// <value><c>true</c> if succeed; otherwise, <c>false</c>.</value>
            public bool Succeed { get { return succeed; } }
        }
        /// <summary>
        /// Response hander for <see cref="SendLoginRequest"/> request.
        /// </summary>
        public delegate void LoginResponseHandler(LoginEventArgs e);

        /// <summary>
        /// Makes the login request to the system.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendLoginRequest(RemoteRequest<LoginResponseHandler, LoginReq> data)
        {
            LoginReq infos = data.State;

            //#region modifies to bypass login
            WS_SoapLogin.SoapUser login = new TripLOAMobile.WS_SoapLogin.SoapUser();
            WS_SoapLogin.WSUser loginRes = null;

            try
            {
                loginRes = login.login(infos.username, infos.password);
                #region bypass login
                /*loginRes = new TripLOAMobile.WS_SoapLogin.WSUser();
                loginRes.Status = okStatus;
                loginRes.Payload=new TripLOAMobile.WS_SoapLogin.UserInfo[]{new TripLOAMobile.WS_SoapLogin.UserInfo()};
                loginRes.AuthToken = "ABC123";*/
                #endregion

                bool succeed = (loginRes.Status == okStatus);
                WS_SoapLogin.UserInfo user = null;
                if (succeed)
                {
                    user = loginRes.Payload[0]; ////Se si notifica via evento
                    actualUser = loginRes.Payload[0];
                    this.authenticationKey = loginRes.AuthToken;

                    this.receivedListOfVehiclesMD5 = loginRes.VehicleListHash;
                    this.receivedBuddyListMD5 = loginRes.BuddyListHash;

                    cred = (Credentials)m_CacheMan.GetCriticalData(infos.username, Credentials.getType());
                    if (cred == null)//se non ho un credential riferito a questo utente in cache
                    {
                        if (data.State.savePassword)
                            cred = new Credentials(infos.username, data.State.password);
                        else
                            cred = new Credentials(infos.username);
                        m_CacheMan.MT_SaveCriticalData(cred, infos.username);
                    }
                    else
                    {
                        //Is the case in which the user decide in a second access to store his password
                        if ((cred.Password == null) && (infos.savePassword))
                        {
                            cred.Password = infos.password;
                            m_CacheMan.MT_SaveCriticalData(cred, infos.username);
                        }
                    }
                }

                string status = loginRes.Status == okStatus ? loginRes.Status : loginRes.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(user, status, succeed));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr), false));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr), false));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr), false));
            }
        }

        /// <summary>
        /// Makes the login request to the system.
        /// This method is called when the password is not specified, but is saved in the cache.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendLoginRequest(RemoteRequest<LoginResponseHandler, string> data)
        {
            string userName = data.State;

            // cred is loaded at the beginning because this login cannot fail 
            //(if the pwd is been saved, a previous login succeeded with this user e pwd)
            cred = (Credentials)m_CacheMan.GetCriticalData(userName, Credentials.getType());

            WS_SoapLogin.SoapUser login = new TripLOAMobile.WS_SoapLogin.SoapUser();
            WS_SoapLogin.WSUser loginRes = null;

            try
            {
                loginRes = login.login(userName, cred.Password);
                #region bypass login
                /*loginRes = new TripLOAMobile.WS_SoapLogin.WSUser();
                loginRes.Status = okStatus;
                loginRes.Payload=new TripLOAMobile.WS_SoapLogin.UserInfo[]{new TripLOAMobile.WS_SoapLogin.UserInfo()};
                loginRes.AuthToken = "ABC123";
                */
                #endregion

                WS_SoapLogin.UserInfo user = null;
                bool succeed = (loginRes.Status == okStatus);
                if (succeed)
                {
                    user = loginRes.Payload[0]; ////Se si notifica via evento
                    actualUser = loginRes.Payload[0];
                    this.authenticationKey = loginRes.AuthToken;
                    
                    this.receivedListOfVehiclesMD5 = loginRes.VehicleListHash;
                    this.receivedBuddyListMD5 = loginRes.BuddyListHash;
                }

                string status = loginRes.Status == okStatus ? loginRes.Status : loginRes.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(user, status, succeed));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr), false));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr), false));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr), false));
            }

            /*
            #region bypass login
            loginRes = new TripLOAMobile.WS_SoapLogin.WSUser();
            loginRes.Status = okStatus;
            loginRes.Payload = new[] { "abc123" };
            #endregion*/

            /*
            //caso senza comunicazioni col sistema
            if (((userName == "pippo") && (cred.Password == "pluto")) || ((userName == "antani") && (cred.Password == "sblinda")))
            {
                this.authenticationKey = "ABCDEF1234";
                return true;
            }
            return false;*/
        }

        /// <summary>
        /// Logouts the current user.
        /// </summary>
        internal void Logout()
        {
            authenticationKey = null;
            actualUser = null;
            booksTracer.Clear();
            favoritesTracer.Clear();
            this.UpdateProfileInCacheIfNeeded();
            this.isListOfVehiclesChanged = false;
            this.isBuddyListChanged = false;
            AnimationControl.USESTANDARDAPPLICATIONANIMATION = true;
            m_CacheMan.Dispose();   //Added to allow a correct saving of the cacheManager (see the Comment) [Andrea Russino]
        }
        #endregion

        #region Methods about GPS
        /// <summary>
        /// Send current GPS position.
        /// </summary>
        /// <param name="latitude">The current latitude</param>
        /// <param name="longitude">The current longitude</param>
        /// <returns>true if everything went ok</returns>
        internal bool SendGPSPosition(double latitude, double longitude)
        {
            throw new NotImplementedException("Not yet implemented");
        }
        #endregion

        #region Methods about trips
        #region InsertTravel
        /// <summary>
        /// Makes an asynchronous request to the system for a travel creation.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="iti">The information for the new travel.</param>
        internal void SendInsertTravelRequest(Control requirer, InsertTravelResponseHandler callback, InsertTravelInfo iti)
        {
            RemoteRequest<InsertTravelResponseHandler, InsertTravelInfo> data = new RemoteRequest<InsertTravelResponseHandler, InsertTravelInfo>(requirer, callback, iti);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendInsertTravelRequest((RemoteRequest<InsertTravelResponseHandler, InsertTravelInfo>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="SendInsertTravelRequest"/>.
        /// Provides the tripID and a status string for each communication.
        /// </summary>
        public class InsertTravelResponseEventArgs : ResponseEventArgs
        {
            int tripID;

            /// <summary>
            /// Initializes a new instance of the <see cref="InsertTravelResponseEventArgs"/> class.
            /// </summary>
            /// <param name="tripID">The trip ID.</param>
            /// <param name="status">The status.</param>
            public InsertTravelResponseEventArgs(int tripID, string status)
                : base(status)
            {
                this.tripID = tripID;
            }

            /// <summary>
            /// Gets the created trip ID.
            /// </summary>
            /// <value>The created trip ID.</value>
            public int InsertedTripID { get { return tripID; } }
        }
        /// <summary>
        /// Response hander for <see cref="SendInsertTravelRequest"/> request.
        /// </summary>
        public delegate void InsertTravelResponseHandler(InsertTravelResponseEventArgs e);

        /// <summary>
        /// Makes the request to the system for a travel creation.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendInsertTravelRequest(RemoteRequest<InsertTravelResponseHandler, InsertTravelInfo> data)
        {
            InsertTravelInfo iti = data.State;

            #region geocoding
            string depAddresGeoCoded;
            string desAddresGeoCoded;
            //se l'utente non ha definito lat e long devo ottenerli tramite delle chiamate al servizio di geocoding
            try
            {
                if (iti.AreDepLatLongDefined)
                {
                    depAddresGeoCoded = iti.LatDep + "," + iti.LongDep;
                }
                else
                {
                    //street,[zipcode] city [province],state
                    depAddresGeoCoded = Welcome.rrp.ST_CheckAddress(iti.getDepartureInFormat());
                    if (depAddresGeoCoded != null)
                    {
                        string[] app = depAddresGeoCoded.Split(',');
                        iti.setDepLatLong(Convert.ToDouble(app[0]), Convert.ToDouble(app[1]));
                    }
                }
                if (iti.AreDesLatLongDefined)
                {
                    desAddresGeoCoded = iti.LatDes + "," + iti.LongDes;
                }
                else
                {
                    desAddresGeoCoded = Welcome.rrp.ST_CheckAddress(iti.getDestinationInFormat());
                    if (desAddresGeoCoded != null)
                    {
                        string[] app = desAddresGeoCoded.Split(',');
                        iti.setDesLatLong(Convert.ToDouble(app[0]), Convert.ToDouble(app[1]));
                    }
                }
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                return;
            }
            catch (SoapException e)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    if (e.Message.Contains("GeoRef.Exceptions.GeoCodingException"))
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(geocodeErr)));
                    else
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                return;
            }
            #endregion
            if ((desAddresGeoCoded != null) && (depAddresGeoCoded != null))
            {
                WS_SoapTrip.SoapTrip soapUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();

                WS_SoapTrip.WSInt res = null;
                try
                {
                    #region creazione fulltripinfo
                    WS_SoapTrip.FullTripInfo trip = new TripLOAMobile.WS_SoapTrip.FullTripInfo();
                    trip.Stages = new TripLOAMobile.WS_SoapTrip.StageInfo[1];
                    trip.Stages[0] = new TripLOAMobile.WS_SoapTrip.StageInfo();
                    trip.Stages[0].Origin = new TripLOAMobile.WS_SoapTrip.PlaceInfo();
                    trip.Stages[0].Origin.Coords = iti.getDepLatLongString();
                    trip.Stages[0].Destination = new TripLOAMobile.WS_SoapTrip.PlaceInfo();
                    trip.Stages[0].Destination.Coords = iti.getDesLatLongString();
                    trip.Stages[0].Vehicle = new TripLOAMobile.WS_SoapTrip.VehicleInfo();
                    trip.Stages[0].Vehicle.VehicleClass = (TripLOAMobile.WS_SoapTrip.VehicleTypes)iti.Veichle;
                    trip.Stages[0].Vehicle.Id = iti.VehicleID;
                    trip.FreeSeats = iti.FreeSeats;
                    trip.AcceptSmoker = iti.Smoker;
                    trip.DepartureDate = iti.DepartureTime;
                    trip.ReservationExpirationDate = trip.DepartureDate; ////By default it is the same of DepartureDate
                    trip.Notes = iti.Comment;
                    trip.IsFrequent = false;
                    trip.Accomplished = false;
                    trip.Draft = iti.Draft;
                    trip.Arrival = iti.getDepartureInFormat();
                    trip.Departure = iti.getDestinationInFormat();
                    trip.DeviationRadius = (iti.MaxDeviation == null) ? 0 : iti.MaxDeviation;
                    trip.EstimatedBudget = iti.EstimatedBudget;
                    trip.EstimatedTime = iti.EstimatedTime;
                    trip.RequireLicensed = iti.LicenseRequired;

                    trip.ID = -1;
                    #endregion

                    res = soapUser.SaveTrip(authenticationKey, trip);

                    string status = res.Status == okStatus ? res.Status : res.Message;

                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(res.Payload, status));
                }
                catch (WebException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                }
                catch (InvalidOperationException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
                catch (SoapException ex)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
            }
                /*
            else
            {
                data.Control.Invoke(data.ResponseHandler, new InsertTravelResponseEventArgs(-1, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString("ambiguity")));
            }     */    
        }
        #endregion

        #region SearchTrip (base & next)
        /// <summary>
        /// Makes an asynchronous request to the system for a travel search.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="criteria">The search criteria.</param>
        internal void SendSearchRequest(Control requirer, TripListResponseHandler callback, SearchCriteria criteria)
        {
            RemoteRequest<TripListResponseHandler, SearchCriteria> data = new RemoteRequest<TripListResponseHandler, SearchCriteria>(requirer, callback, criteria);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendSearchRequest((RemoteRequest<TripListResponseHandler, SearchCriteria>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to all requests that return a list of <see cref="TripInfo"/>, 
        /// such as <see cref="SendSearchRequest"/>, <see cref="Next"/>, 
        /// <see cref="GetAllMyBookings"/>, <see cref="GetAllMyOffered"/>
        /// and <see cref="GetAllMyDraft"/>.
        /// Provides the list of trips and a status string for each communication.
        /// </summary>
        public class TripListResponseEventArgs : ResponseEventArgs
        {
            WS_SoapTrip.TripInfo[] results;

            /// <summary>
            /// Initializes a new instance of the <see cref="TripListResponseEventArgs"/> class.
            /// </summary>
            /// <param name="results">The results.</param>
            /// <param name="status">The status.</param>
            public TripListResponseEventArgs(WS_SoapTrip.TripInfo[] results, string status)
                : base(status)
            {
                this.results = results;
            }

            /// <summary>
            /// Gets the results.
            /// </summary>
            /// <value>The results.</value>
            public WS_SoapTrip.TripInfo[] Results { get { return results; } }
        }
        /// <summary>
        /// Response hander for <see cref="SendSearchRequest"/>, <see cref="Next"/>, 
        /// <see cref="GetAllMyBookings"/>, <see cref="GetAllMyOffered"/>
        /// and <see cref="GetAllMyDraft"/> requests.
        /// </summary>
        public delegate void TripListResponseHandler(TripListResponseEventArgs e);

        /// <summary>
        /// Makes the request to the system for a travel search.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendSearchRequest(RemoteRequest<TripListResponseHandler, SearchCriteria> data)
        {
            SearchCriteria criteria = data.State;

            this.lastSearchedCriteria = criteria;

            #region geocoding
            string depAddresGeoCoded;
            string desAddresGeoCoded;
            //se l'utente non ha definito lat e long devo ottenerli tramite delle chiamate al servizio di geocoding
            try
            {
                if (criteria.AreDepLatLongDefined)
                {
                    depAddresGeoCoded = criteria.LatDep + "," + criteria.LongDep;
                }
                else
                {
                    //street,[zipcode] city [province],state
                    depAddresGeoCoded = Welcome.rrp.ST_CheckAddress(criteria.getDepartureInFormat());
                    if (depAddresGeoCoded != null)
                    {
                        string[] app = depAddresGeoCoded.Split(',');
                        criteria.setDepLatLong(Convert.ToDouble(app[0]), Convert.ToDouble(app[1]));
                    }
                }
                if (criteria.AreDesLatLongDefined)
                {
                    desAddresGeoCoded = criteria.LatDes + "," + criteria.LongDes;
                }
                else
                {
                    desAddresGeoCoded = Welcome.rrp.ST_CheckAddress(criteria.getDestinationInFormat());
                    if (desAddresGeoCoded != null)
                    {
                        string[] app = desAddresGeoCoded.Split(',');
                        criteria.setDesLatLong(Convert.ToDouble(app[0]), Convert.ToDouble(app[1]));
                    }
                }
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                return;
            }
            catch (SoapException e)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    if (e.Message.Contains("GeoRef.Exceptions.GeoCodingException"))
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(geocodeErr)));
                    else
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                return;
            }
            #endregion

            //Ora so che in 
            //criteria may contains not all the four parameters...tiri fuori info da criteria e mandi la richiesta ai ws...
            if ((depAddresGeoCoded != null) && (desAddresGeoCoded != null))
            {
                this.latestIndexReturned = 0;

                WS_SoapTrip.SoapTrip soapUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
                WS_SoapTrip.WSTrip searchResult = null;

                try
                {
                    searchResult = soapUser.TripSearch(authenticationKey, depAddresGeoCoded, desAddresGeoCoded, criteria.FromTime, criteria.ToTime, 0, maxNumberOfResult + 1);
                    if (searchResult.Status == okStatus)
                        latestIndexReturned = searchResult.Payload.Length - 1;

                    string status = searchResult.Status == okStatus ? searchResult.Status : searchResult.Message;

                    if (data.Control != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs((searchResult.Status == okStatus) ? searchResult.Payload : null, status));
                }
                catch (WebException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                }
                catch (InvalidOperationException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
                catch (SoapException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
            }
            /*
            else
            {
                data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString("ambiguity")));
            }*/
        }

        /// <summary>
        /// Makes an asynchronous request to the system for the next portion of results of the last search made.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        internal void Next(Control requirer, TripListResponseHandler callback)
        {
            RemoteRequest<TripListResponseHandler, object> data = new RemoteRequest<TripListResponseHandler, object>(requirer, callback, null);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_Next((RemoteRequest<TripListResponseHandler, object>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes the request to the system for the next portion of results of the last search made.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_Next(RemoteRequest<TripListResponseHandler, object> data)
        {
            WS_SoapTrip.SoapTrip soapUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            WS_SoapTrip.WSTrip searchResult;
            try
            {
                searchResult = soapUser.TripSearch(authenticationKey, lastSearchedCriteria.Departure, lastSearchedCriteria.Destination, lastSearchedCriteria.FromTime, lastSearchedCriteria.ToTime, this.latestIndexReturned, maxNumberOfResult);

                TripListResponseEventArgs args;
                if (searchResult.Status == okStatus)
                {
                    latestIndexReturned += (searchResult.Payload.Length - 1);
                    args = new TripListResponseEventArgs(searchResult.Payload, searchResult.Status);
                }
                else
                    args = new TripListResponseEventArgs(null, searchResult.Status);

                string status = searchResult.Status == okStatus ? searchResult.Status : searchResult.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, args);
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new LoginEventArgs(CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr), false));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion

        #region GetDetails
        /// <summary>
        /// Makes an asynchronous request to the system for a travel details.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="id">The travel id.</param>
        internal void GetDetails(Control requirer, DetailsResponseHandler callback, int id)
        {
            RemoteRequest<DetailsResponseHandler, int> data = new RemoteRequest<DetailsResponseHandler, int>(requirer, callback, id);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetDetails((RemoteRequest<DetailsResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="GetDetails"/>.
        /// Provides all the trip details and a status string for each communication.
        /// </summary>
        public class DetailsResponseEventArgs : ResponseEventArgs
        {
            WS_SoapTrip.FullTripInfo details;

            /// <summary>
            /// Initializes a new instance of the <see cref="DetailsResponseEventArgs"/> class.
            /// </summary>
            /// <param name="details">The details.</param>
            /// <param name="status">The status.</param>
            public DetailsResponseEventArgs(WS_SoapTrip.FullTripInfo details, string status)
                : base(status)
            {
                this.details = details;
            }

            /// <summary>
            /// Gets the trip details.
            /// </summary>
            /// <value>The trip details.</value>
            public WS_SoapTrip.FullTripInfo Details { get { return details; } }
        }
        /// <summary>
        /// Response hander for <see cref="GetDetails"/> requests.
        /// </summary>
        public delegate void DetailsResponseHandler(DetailsResponseEventArgs e);

        /// <summary>
        /// Makes a request to the system for a travel details.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetDetails(RemoteRequest<DetailsResponseHandler, int> data)
        {
            int travelId = data.State;

            WS_SoapTrip.SoapTrip ws = new WS_SoapTrip.SoapTrip();
            WS_SoapTrip.WSFullTrip res;

            try
            {
                res = ws.GetTripDetails(authenticationKey, travelId);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new DetailsResponseEventArgs((res.Status == okStatus) ? res.Payload[0] : null, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new DetailsResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new DetailsResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new DetailsResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion
        #endregion

        #region Methods about geocoding
        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="SendReverseGeoCodingRequest"/>.
        /// Provides all the trip details and a status string for each communication.
        /// </summary>
        public class GeoCodeResponseEventArgs : ResponseEventArgs
        {
            string address;

            /// <summary>
            /// Initializes a new instance of the <see cref="GeoCodeResponseEventArgs"/> class.
            /// </summary>
            /// <param name="address">The reverse geocoded address.</param>
            /// <param name="status">The status.</param>
            public GeoCodeResponseEventArgs(string address, string status)
                : base(status)
            {
                this.address = address;
            }

            /// <summary>
            /// Gets the reverse geocoded address.
            /// </summary>
            /// <value>The reverse geocoded address.</value>
            public string Address { get { return address; } }
        }
        /// <summary>
        /// Response hander for <see cref="SendReverseGeoCodingRequest"/> requests.
        /// </summary>
        public delegate void GeoCodeResponseHandler(GeoCodeResponseEventArgs e);

        /// <summary>
        /// Makes an asynchronous request to the system for a reverse geocoding.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="id">The location as a geographic point.</param>
        public void SendReverseGeoCodingRequest(Control requirer, GeoCodeResponseHandler callback, WS_GeoRef.GeoPoint point)
        {
            RemoteRequest<GeoCodeResponseHandler, WS_GeoRef.GeoPoint> data = new RemoteRequest<GeoCodeResponseHandler, WS_GeoRef.GeoPoint>(requirer, callback, point);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendReverseGeoCodingRequest((RemoteRequest<GeoCodeResponseHandler, WS_GeoRef.GeoPoint>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a reverse geocoding.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendReverseGeoCodingRequest(RemoteRequest<GeoCodeResponseHandler, WS_GeoRef.GeoPoint> data)
        {
            WS_GeoRef.GeoPoint point = data.State;

            WS_GeoRef.SoapGeoRef soapUserGeoRef = new TripLOAMobile.WS_GeoRef.SoapGeoRef();
            WS_GeoRef.WSGeoLoc callRes = null;

            try
            {
                callRes = soapUserGeoRef.reverseGeoCoding(point.Lat, point.Lng);

                string status = callRes.Status == okStatus ? callRes.Status : callRes.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs(callRes.Payload[0].Address, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for an address anbiguity checking.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>/// <param name="address">The address.</param>
        public void CheckAddress(Control requirer, GeoCodeResponseHandler callback, string address)
        {
            RemoteRequest<GeoCodeResponseHandler, string> data = new RemoteRequest<GeoCodeResponseHandler, string>(requirer, callback, address);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_CheckAddress((RemoteRequest<GeoCodeResponseHandler, string>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a reverse geocoding.
        /// Multi-Threaded implementation, invoked through CheckAddress.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_CheckAddress(RemoteRequest<GeoCodeResponseHandler, string> data)
        {
            string address = data.State;

            WS_GeoRef.SoapGeoRef soapUserGeoRef = new TripLOAMobile.WS_GeoRef.SoapGeoRef();
            WS_GeoRef.WSGeoLoc res;
            WS_GeoRef.GeoLoc[] listOfAlternatives;
            try
            {
                if (!address.isLatLong())
                {
                    string state = address.getState();
                    string city = address.getCity();
                    string street = address.getStreet();

                    res = soapUserGeoRef.geoCoding(address.getState(), address.getCity(),
                        "", address.getStreet());

                    if (res.Status == okStatus)
                    {
                        listOfAlternatives = res.Payload;

                        if (listOfAlternatives.Length > 1)
                        {
                            //the address is ambiguous, let the user choose...
                            DisplayAlternativeAddresses daa = new DisplayAlternativeAddresses(listOfAlternatives);
                            Welcome.formBuffer.Add(daa, "DisplayAlternativeAddresses");
                            daa.ShowDialog();
                            daa.Dispose();

                            if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                                data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs(daa.LatLongSelected, okStatus));
                        }
                        else
                            if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                                data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs(listOfAlternatives[0].Lat + "," + listOfAlternatives[0].Lng, okStatus));
                    }
                    else
                        if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                            data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", res.Message));
                }
                else
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs(address, okStatus));
                }
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new GeoCodeResponseEventArgs("", CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes a request to the system for a reverse geocoding.
        /// Single-Threaded implementation.
        /// </summary>
        /// <param name="address">The address to check, espressed as "Lan,Long" format.</param>
        /// <returns>The corresponding reverse geocoded address.</returns>
        private string ST_CheckAddress(string address)
        {
            WS_GeoRef.SoapGeoRef soapUserGeoRef = new TripLOAMobile.WS_GeoRef.SoapGeoRef();
            WS_GeoRef.WSGeoLoc res;
            WS_GeoRef.GeoLoc[] listOfAlternatives;

            if (!address.isLatLong())
            {
                string state = address.getState();
                string city = address.getCity();
                string street = address.getStreet();

                res = soapUserGeoRef.geoCoding(address.getState(), address.getCity(),
                    "", address.getStreet());

                if (res.Status == okStatus)
                {
                    listOfAlternatives = res.Payload;
                    if (listOfAlternatives.Length > 1)
                    {
                        //the address is ambiguous, let the user choose...
                        DisplayAlternativeAddresses daa = new DisplayAlternativeAddresses(listOfAlternatives);
                        Welcome.formBuffer.Add(daa, "DisplayAlternativeAddresses");
                        daa.ShowDialog();
                        daa.Dispose();
                        return daa.LatLongSelected;
                    }
                    else
                        return listOfAlternatives[0].Lat + "," + listOfAlternatives[0].Lng;
                }
                else
                    //l'indirizzo non corrisponde a niente...avvisare l'utente...
                    return address;//non è vero...aprire form e mostrarla all'utente...e ritornare...
            }
            else
                //indirizzo è già sottoforma di latitudine e longitudine.
                return address;
        }
        #endregion

        #region Methods about booking
        /// <summary>
        /// Makes an asynchronous request to the system for a booking.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="rr">The booking details.</param>
        internal void SendBookingTravelRequest(Control requirer, BooleanResponseHandler callback, ReservationRequest rr)
        {
            RemoteRequest<BooleanResponseHandler, ReservationRequest> data = new RemoteRequest<BooleanResponseHandler, ReservationRequest>(requirer, callback, rr);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendBookingTravelRequest((RemoteRequest<BooleanResponseHandler, ReservationRequest>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to all that requests that require a boolean response.
        /// Provides a boolean response and a status string for each communication.
        /// </summary>
        public class BooleanResponseEventArgs : ResponseEventArgs
        {
            bool succeed;

            /// <summary>
            /// Initializes a new instance of the <see cref="BooleanResponseEventArgs"/> class.
            /// </summary>
            /// <param name="succeed">Set to <c>true</c> if succeed.</param>
            /// <param name="status">The status.</param>
            public BooleanResponseEventArgs(bool succeed, string status)
                : base(status)
            {
                this.succeed = succeed;
            }

            /// <summary>
            /// Gets a value indicating whether this <see cref="BooleanResponseEventArgs"/> is succeed.
            /// </summary>
            /// <value><c>true</c> if succeed; otherwise, <c>false</c>.</value>
            public bool Succeed { get { return succeed; } }
        }
        /// <summary>
        /// Response hander for that requests that require a boolean response.
        /// </summary>
        public delegate void BooleanResponseHandler(BooleanResponseEventArgs e);

        /// <summary>
        /// Makes a request to the system for a booking.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendBookingTravelRequest(RemoteRequest<BooleanResponseHandler, ReservationRequest> data)
        {
            ReservationRequest bookingParameters = data.State;

            TripLOAMobile.WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            #region geocoding
            try
            {
                string coord;
                if (bookingParameters.FromCoords == null)
                {
                    coord = Welcome.rrp.ST_CheckAddress(bookingParameters.Departure);
                    bookingParameters.FromCoords = coord;
                }
                if (bookingParameters.ToCoords == null)
                {
                    coord = Welcome.rrp.ST_CheckAddress(bookingParameters.Arrival);
                    bookingParameters.ToCoords = coord;
                }
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                return;
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                return;
            }
            #endregion


            WS_SoapTrip.WSBool res = null;
            try
            {
                res = serviceUser.RequestReservation(this.authenticationKey, bookingParameters.TravelID, bookingParameters.FromCoords, bookingParameters.ToCoords, bookingParameters.NSeats, bookingParameters.Tolerance, bookingParameters.Notes);
                if (res.Payload)
                    this.booksTracer.Add(bookingParameters.TravelID, true);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, res.Status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException ex)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                return;
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for all personal bookings.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void GetAllMyBookings(Control requirer, TripListResponseHandler callback, int numberOfRequest)
        {
            RemoteRequest<TripListResponseHandler, int> data = new RemoteRequest<TripListResponseHandler, int>(requirer, callback, numberOfRequest);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetAllMyBookings((RemoteRequest<TripListResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for all personal bookings.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetAllMyBookings(RemoteRequest<TripListResponseHandler, int> data)
        {
            //It takes informations from cache and from the central system (send version to the system. I it is coherent there no need to receive...)

            int numberOfRequest = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            WS_SoapTrip.WSTrip res = null;
            try
            {
                int offsetStart = 0, offsetMax = 0;
                if (numberOfRequest == 0)
                    offsetMax = 1;
                else
                    offsetStart = 1;
                res = serviceUser.BookedTrips(this.authenticationKey, numberOfRequest * maxNumberOfResult + offsetStart, (numberOfRequest + 1) * maxNumberOfResult + offsetMax);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a booking canceling.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void SendCancelBookingRequest(Control requirer, BooleanResponseHandler callback, int travelId)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, travelId);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendCancelBookingRequest((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a booking canceling.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendCancelBookingRequest(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int travelID = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            WS_SoapTrip.WSBool res = null;
            try
            {
                res = serviceUser.CancelTrip(this.authenticationKey, travelID);
                if (res.Payload)
                    this.booksTracer.Remove(travelID);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a booking check.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="travelId">The travel id.</param>
        internal void IsBooked(Control requirer, BooleanResponseHandler callback, int travelId)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, travelId);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_IsBooked((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a booking check.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_IsBooked(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int travelID = data.State;

            WS_SoapTrip.WSBool app = null;

            if (this.booksTracer.ContainsKey(travelID))
            {
                if (data.Control != null && data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(true, okStatus));
            }
            else
            {
                WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
                try
                {
                    app = serviceUser.IsBooked(this.authenticationKey, travelID);

                    string status = app.Status == okStatus ? app.Status : app.Message;

                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(app.Payload, status));
                }
                catch (WebException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                }
                catch (InvalidOperationException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
                catch (SoapException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
            }
        }
        #endregion

        #region Methods about favorites
        /// <summary>
        /// Makes an asynchronous request to the system for a favorite check.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="travelId">The travel id.</param>
        internal void IsFavorite(Control requirer, BooleanResponseHandler callback, int travelId)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, travelId);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_IsFavorite((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a favorite check.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_IsFavorite(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int travelId = data.State;

            WS_SoapTrip.WSBool app = null;
            //dovrebbe andare bene fare così, tanto finchè sono loggato, nessuno può levarlo dai miei preferiti...
            if (this.favoritesTracer.ContainsKey(travelId))
            {
                if (data.Control != null)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(true, okStatus));
            }
            else
            {
                WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
                try
                {
                    app = serviceUser.IsInFavorites(this.authenticationKey, travelId);

                    string status = app.Status == okStatus ? app.Status : app.Message;

                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(app.Payload, status));

                }
                catch (WebException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
                }
                catch (InvalidOperationException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
                catch (SoapException)
                {
                    if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                        data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
                }
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a favorite marking.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void SendAddToFavoritesRequest(Control requirer, BooleanResponseHandler callback, int travelId)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, travelId);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendAddToFavoritesRequest((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a favorite marking.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendAddToFavoritesRequest(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int travelId = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            try
            {
                WS_SoapTrip.WSBool res = serviceUser.AddTripToFavorites(this.authenticationKey, travelId);

                if (res.Payload)
                    this.favoritesTracer.Add(travelId, true);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /// <summary>
        /// Makes an asynchronous request to the system for a favorite unmarking.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void SendRemoveFromFavoritesRequest(Control requirer, BooleanResponseHandler callback, int travelId)
        {
            RemoteRequest<BooleanResponseHandler, int> data = new RemoteRequest<BooleanResponseHandler, int>(requirer, callback, travelId);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_SendRemoveFromFavoritesRequest((RemoteRequest<BooleanResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for a favorite unmarking.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_SendRemoveFromFavoritesRequest(RemoteRequest<BooleanResponseHandler, int> data)
        {
            int travelId = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            try
            {
                WS_SoapTrip.WSBool res = serviceUser.RemoveTripFromFavorites(this.authenticationKey, travelId);

                if (res.Payload)
                    this.favoritesTracer.Remove(travelId);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new BooleanResponseEventArgs(false, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion

        #region Methods about the managing of the travels
        /// <summary>
        /// Makes an asynchronous request to the system for all the offered travels.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void GetAllMyOfferedTravel(Control requirer, TripListResponseHandler callback, int numberOfRequest)
        {
            RemoteRequest<TripListResponseHandler, int> data = new RemoteRequest<TripListResponseHandler, int>(requirer, callback, numberOfRequest);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetAllMyOfferedTravel((RemoteRequest<TripListResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for all the offered travels.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetAllMyOfferedTravel(RemoteRequest<TripListResponseHandler, int> data)
        {
            int numberOfRequest = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            //WS_SoapTrip.TripInfo[] listOfOffereedTrip;
            try
            {
                int offsetStart = 0, offsetMax = 0;
                if (numberOfRequest == 0)
                    offsetMax = 1;
                else
                    offsetStart = 1;

                WS_SoapTrip.WSTrip res = serviceUser.OfferedTrips(this.authenticationKey, maxNumberOfResult * numberOfRequest + offsetStart, maxNumberOfResult * (numberOfRequest + 1) + offsetMax);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }

        /* This is a fake method, not supported by the system.
        /// <summary>
        /// Returns the list of draft of travel (travel partially defined by the mobile user).
        /// It takes informations from cache and from the central system (maybe the same user could have created/modified a draft, (send version to the system. I it is coherent there no need to receive))
        /// </summary>
        /// <param name="numberOfRequest">The number of requests made</param>
        /// <param name="maxNumberTravel">The maximum number of travel to return</param>
        /// <returns>the list of favorites travel</returns>
        internal WS_SoapTrip.TripInfo[] GetAllMyDraftTravel(int numberOfRequest, int maxNumberTravel, out string status)
        {
            throw new NotImplementedException("This is a FakeMethod");
            ///////////////Quando verrà utilizzato allora verrà reso multithreaded, per il momento rimane!!!

            status = okStatus;
            WS_SoapTrip.TripInfo[] listOfOfFavoritesTrip = new TripLOAMobile.WS_SoapTrip.TripInfo[4];
            var t = new TripLOAMobile.WS_SoapTrip.TripInfo();
            t.ID = 8;
            t.Departure = "Milano";
            t.Arrival = "Roma";
            //t.AcceptSmokers = false;
            t.DepartureDate = DateTime.Now;
            //t.FreeSeatNumber = 2;
            t.EstimatedBudget = 20;
            //t.EstimatedTime = 11;
            listOfOfFavoritesTrip[0] = t;
            t = new TripLOAMobile.WS_SoapTrip.TripInfo();
            t.ID = 9;
            t.Departure = "Milano";
            t.Arrival = "Napoli";
            listOfOfFavoritesTrip[1] = t;
            t = new TripLOAMobile.WS_SoapTrip.TripInfo();
            t.ID = 10;
            t.Departure = "La Spezia";
            t.Arrival = "Roma";
            listOfOfFavoritesTrip[2] = t;
            t = new TripLOAMobile.WS_SoapTrip.TripInfo();
            t.ID = 11;
            t.Departure = "La Spezia";
            t.Arrival = "Verona";
            listOfOfFavoritesTrip[3] = t;


            //WS_SoapTrip.TripInfo[] listOfOfFavoritesTrip;
            //WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            //WS_SoapTrip.WSTrip res=serviceUser.
            return listOfOfFavoritesTrip;
        }
        */

        /// <summary>
        /// Makes an asynchronous request to the system for all the favorite travels.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        internal void GetAllMyFavoritesTravel(Control requirer, TripListResponseHandler callback, int numberOfRequest)
        {
            RemoteRequest<TripListResponseHandler, int> data = new RemoteRequest<TripListResponseHandler, int>(requirer, callback, numberOfRequest);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetAllMyFavoritesTravel((RemoteRequest<TripListResponseHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for all the favorite travels.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetAllMyFavoritesTravel(RemoteRequest<TripListResponseHandler, int> data)
        {
            // It takes informations from cache and from the central system (send version to the system. I it is coherent there no need to receive...)
            int numberOfRequest = data.State;

            WS_SoapTrip.SoapTrip serviceUser = new TripLOAMobile.WS_SoapTrip.SoapTrip();
            try
            {
                int offsetStart = 0, offsetMax = 0;
                if (numberOfRequest == 0)
                    offsetMax = 1;
                else
                    offsetStart = 1;

                WS_SoapTrip.WSTrip res = serviceUser.FavoritesTrips(this.authenticationKey, maxNumberOfResult * numberOfRequest + offsetStart, maxNumberOfResult * (numberOfRequest + 1) + offsetMax);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new TripListResponseEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion

        #region regionOfNotification
        /// <summary>
        /// ResponseEvent raised on a response receiving from the system
        /// to <see cref="GetNotificationList"/>.
        /// Provides the notification list and a status string for each communication.
        /// </summary>
        public class NotificationListResposeEventArgs : ResponseEventArgs
        {
            WS_SoapLogin.Notification[] results;

            /// <summary>
            /// Initializes a new instance of the <see cref="NotificationListResposeEventArgs"/> class.
            /// </summary>
            /// <param name="results">The results.</param>
            /// <param name="status">The status.</param>
            public NotificationListResposeEventArgs(WS_SoapLogin.Notification[] results, string status)
                : base(status)
            {
                this.results = results;
            }

            /// <summary>
            /// Gets the notification list.
            /// </summary>
            /// <value>The notification list.</value>
            public WS_SoapLogin.Notification[] Results { get { return this.results; } }
        }
        /// <summary>
        /// Response hander for <see cref="GetNotificationList"/> request.
        /// </summary>
        public delegate void NotificationListResposeHandler(NotificationListResposeEventArgs e);

        /// <summary>
        /// Makes an asynchronous request to the system for all pending notifications.
        /// When the request is satisfied the response event handler is called.
        /// </summary>
        /// <param name="requirer">The requirer control (the control to which return a response).</param>
        /// <param name="callback">The response event handler.</param>
        /// <param name="numberOfRequest">The number of request items.</param>
        public void GetNotificationList(Control requirer, NotificationListResposeHandler callback, int numberOfRequest)
        {
            RemoteRequest<NotificationListResposeHandler, int> data = new RemoteRequest<NotificationListResposeHandler, int>(requirer, callback, numberOfRequest);
            System.Threading.WaitCallback job =
                delegate(object state) { MT_GetNotificationList((RemoteRequest<NotificationListResposeHandler, int>)state); };
            System.Threading.ThreadPool.QueueUserWorkItem(job, data);
        }

        /// <summary>
        /// Makes a request to the system for all pending notifications.
        /// </summary>
        /// <param name="data">The data associated to the request.</param>
        private void MT_GetNotificationList(RemoteRequest<NotificationListResposeHandler, int> data)
        {
            int numberOfRequest = data.State;
            WS_SoapLogin.SoapUser notification = new TripLOAMobile.WS_SoapLogin.SoapUser();

            try
            {
                int offsetStart = 0, offsetMax = 0;
                if (numberOfRequest == 0)
                    offsetMax = 1;
                else
                    offsetStart = 1;

                WS_SoapLogin.WSNotification res = notification.GetUserNotificationsList(this.authenticationKey);

                string status = res.Status == okStatus ? res.Status : res.Message;

                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new NotificationListResposeEventArgs(res.Payload, status));
            }
            catch (WebException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new NotificationListResposeEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(connErr)));
            }
            catch (InvalidOperationException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new NotificationListResposeEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
            catch (SoapException)
            {
                if (data.Control != null && data.ResponseHandler != null && !data.Control.IsDisposed)
                    data.Control.Invoke(data.ResponseHandler, new NotificationListResposeEventArgs(null, CompactFramework.Utilities.Localization.ResourceManager.Instance.GetString(serverErr)));
            }
        }
        #endregion
    }
}